#ifndef _RETRO_D3DDISPLAY
#define _RETRO_D3DDISPLAY

#include <d3dx9.h>

#define D3DFVF_TLVERTEX     (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1)

namespace Retro
{
  namespace Device
  {
    namespace Display
    {
      struct TLVERTEX
      {
        REAL x;
        REAL y;
        REAL z;
        //REAL rhw;
        D3DCOLOR colour;
        REAL u;
        REAL v;
      };

      class D3DTexture : public Texture
      {
      private:
        LPDIRECT3DTEXTURE9 mD3DTexture;

      public:
        virtual BOOL  initialize(IDevice* iDevice);
        virtual VOID  uninitialize();

        INL LPDIRECT3DTEXTURE9 getD3DTexture()
        {
          return mD3DTexture;
        }

        D3DTexture();
      };

      class DLLEXPORT D3DFont : public Font
      {
      private:
        LPD3DXFONT    mD3DFont;

      public:
        virtual BOOL  initialize(IDevice* iDevice);
        virtual VOID  uninitialize();

        INL LPD3DXFONT getD3DFont()
        {
          return mD3DFont;
        }

        D3DFont();
      };

      class DLLEXPORT D3DDisplay : public DisplayDevice
      {
      private:
        LPDIRECT3D9             mD3D;
        D3DPRESENT_PARAMETERS   mD3DParams;
        LPDIRECT3DDEVICE9       mD3DDevice;
        LPD3DXSPRITE            mD3DSprite;
        LPD3DXLINE              mD3DLine;

        IDirect3DVertexBuffer9* mD3DVertexBuffer;
        IDirect3DVertexBuffer9* mD3DBatchBuffer;
        IDirect3DIndexBuffer9*  mD3DIndexBuffer;
        UINT                    mBatchCount;
        TLVERTEX*               mBatchVertices;

      public:
        virtual BOOL initialize();
        virtual BOOL uninitialize();
        virtual BOOL isInitialized();

        virtual BOOL isWireframe();
        virtual BOOL setWireframe(BOOL iValue);

        virtual DisplayMode getDisplayMode();
        virtual BOOL        setDisplayMode(DisplayMode iValue);

        virtual BOOL getDisplaySize(Geom::Size& oSize);

        virtual Font* createFont(
          PCTSTR iFacename,
          UINT iHeight,
          UINT iWeight,
          BOOL iItalic
          );
        virtual Texture* createTexture(
          PCTSTR iPath
          );

        INL LPDIRECT3DDEVICE9 getDevice()
        {
          return mD3DDevice;
        }

        virtual BOOL  drawTexture(
          Texture* iTexture,
          const Geom::Bounds& iDest,
          const Geom::Bounds *iSrc,
          COLOR iColorTL,
          COLOR iColorTR,
          COLOR iColorBL,
          COLOR iColorBR
          );

        virtual BOOL  drawString(
          Font* iFont,
          LPCTSTR iText,
          DWORD iFormat,
          DWORD iColor,
          const Geom::Bounds& iDest
          );

        virtual BOOL  fillRectangle(
          const Geom::Bounds& iDest,
          COLOR iColorTL,
          COLOR iColorTR,
          COLOR iColorBL,
          COLOR iColorBR
          );

        virtual BOOL  drawRectangle(
          const Geom::Bounds& iDest,
          COLOR iColor
          );
        virtual BOOL  drawLine(
          LONG iX1,
          LONG iY1,
          LONG iX2,
          LONG iY2,
          COLOR iColor
          );

        virtual VOID  resetTransform(
          MatrixType iType = MatrixWorld
          );
        virtual VOID  transform(
          const Vector::Vector2D& iScaleCenter,
          const Vector::Vector2D& iScale,
          const Vector::Vector2D& iRotateCenter,
          REAL iRotate,
          const Vector::Vector2D& iTranslate,
          MatrixType iType = MatrixWorld
          );

        virtual VOID  setAlpha(BYTE value);
        virtual VOID  setLightness(BYTE value);

        virtual VOID  setRenderEffect(RenderEffect iValue);
        virtual VOID  setRenderTarget(Texture* iValue);

        virtual BOOL  beginScene();
        virtual BOOL  endScene();

        virtual BOOL  beginTexture();
        virtual BOOL  beginFont();
        virtual BOOL  beginLine(
          FLOAT iWidth = 1.0f,
          DWORD iPattern = 0xFFFFFFFF,
          FLOAT iPatternScale = 1.0f
          );
        virtual BOOL  beginBatch(
          Texture* iTexture
          );
        virtual BOOL  end();

        virtual BOOL  clear(COLOR iValue);

        virtual BOOL  addBatch(
          const Geom::Bounds& iDest,
          const Geom::Bounds* iSource,
          COLOR iColorTL,
          COLOR iColorTR,
          COLOR iColorBL,
          COLOR iColorBR
          );

        D3DDisplay();
        ~D3DDisplay();
      };
    } // namespace Display
  } // namespace Device
} // namespace Retro

#endif
